package com.masterkey;

import java.io.IOException;
import java.nio.charset.Charset;
import java.util.*;
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.PendingIntent;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.IntentFilter.MalformedMimeTypeException;
import android.nfc.*;
import android.nfc.tech.*;
import android.os.Bundle;
import android.os.Parcelable;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.Log;
import android.view.View;
import android.widget.*;
import com.db4o.*;

import android.nfc.NdefMessage;
import android.nfc.NdefRecord;
import android.nfc.NfcAdapter;
import android.widget.TextView;

public class GetPW extends Activity {

	TextView userName, password;
	TextView userNameText, passwordText;
	Spinner spinner;
	Data retrievedData;
	String siteAppString;
	String decryptedPW;
	Button get, change, write, read;
	byte[] encryptedPW;
	SecretKeySpec skeySpec;
	ObjectContainer oc;

	// boolean sending = false;
	boolean gotData = false;

	private static final String TAG = "stickynotes";
	private boolean mResumed = false;
	private boolean mWriteMode = false;
	NfcAdapter mNfcAdapter;
	String mNote;

	PendingIntent mNfcPendingIntent;
	IntentFilter[] mWriteTagFilters;
	IntentFilter[] mNdefExchangeFilters;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		// TODO Auto-generated method stub
		super.onCreate(savedInstanceState);
		setContentView(R.layout.getpw);

		spinner = (Spinner) findViewById(R.id.spinner2);
		ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(
				this, R.array.apps_sites_array,
				android.R.layout.simple_spinner_item);
		adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
		spinner.setAdapter(adapter);

		userName = (TextView) findViewById(R.id.un);
		password = (TextView) findViewById(R.id.pw);
		userNameText = (TextView) findViewById(R.id.unText);
		passwordText = (TextView) findViewById(R.id.pwText);
		change = (Button) findViewById(R.id.changePW);

		spinner.setOnItemSelectedListener(new MyOnItemSelectedListener());
		
		
		
		get = (Button) findViewById(R.id.getPW);
		get.setOnClickListener(new View.OnClickListener() {

			public void onClick(View v) {

				System.out.println("dodo arnobha !");
				siteAppString = spinner.getSelectedItem().toString();

				oc = Db4oEmbedded.openFile(Db4oEmbedded.newConfiguration(),
						"/sdcard/MasterKeyDB");

				Data data = new Data(siteAppString, null, null, null);
				ObjectSet result = oc.queryByExample(data);
				listResult(result);
				oc.close();

				userName.setVisibility(0);
				userNameText.setVisibility(0);
				password.setVisibility(0);
				passwordText.setVisibility(0);

				if (retrievedData != null) {

					mNote = retrievedData.toString();

					encryptedPW = retrievedData.getEncryptedPW();
					skeySpec = retrievedData.getSkeySpec();

					try {

						decrypt();

					} catch (Exception e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}

					userName.setText(retrievedData.getUserName());
					password.setText(decryptedPW.toString());
					change.setVisibility(0);
					read.setVisibility(0);
					write.setVisibility(0);
					gotData = true;

				} else {

					userName.setText("No user name is saved.");
					password.setText("No password is saved.");
				}

			}
		});

		change = (Button) findViewById(R.id.changePW);
		change.setOnClickListener(new View.OnClickListener() {
			public void onClick(View v) {
				
				// Changed from Rasheed
				Intent i = new Intent(GetPW.this, ChangePW.class);
				i.putExtra("userName", retrievedData.getUserName());
				i.putExtra("password", decryptedPW.toString());
				startActivity(i);
				
				// ....
			}
		});

		/* NFC */

		mNfcAdapter = NfcAdapter.getDefaultAdapter(this);

		write = (Button) findViewById(R.id.writePW);
		write.setOnClickListener(mTagWriter);
		// mNote = ((EditText) findViewById(R.id.note));
		// if (gotData) {
		// mNote = retrievedData.toString();
		// }
		// mNote.addTextChangedListener(mTextWatcher);

		// Handle all of our received NFC intents in this activity.
		mNfcPendingIntent = PendingIntent.getActivity(this, 0, new Intent(this,
				getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0);

		// Intent filters for reading a note from a tag or exchanging over p2p.
		IntentFilter ndefDetected = new IntentFilter(
				NfcAdapter.ACTION_NDEF_DISCOVERED);

		try {
			ndefDetected.addDataType("text/plain");
		} catch (MalformedMimeTypeException e) {
		}

		mNdefExchangeFilters = new IntentFilter[] { ndefDetected };

		// Intent filters for writing to a tag
		IntentFilter tagDetected = new IntentFilter(
				NfcAdapter.ACTION_TAG_DISCOVERED);
		mWriteTagFilters = new IntentFilter[] { tagDetected };

		read = (Button) findViewById(R.id.readPW);
		read.setOnClickListener(new View.OnClickListener() {
			public void onClick(View v) {

			}
		});

	}

	public void listResult(List<?> result) {

		for (Object o : result) {
			retrievedData = (Data) o;
		}
	}

	public static String asHex(byte buf[]) {

		StringBuffer strbuf = new StringBuffer(buf.length * 2);
		int i;

		for (i = 0; i < buf.length; i++) {

			if (((int) buf[i] & 0xff) < 0x10)
				strbuf.append("0");

			strbuf.append(Long.toString((int) buf[i] & 0xff, 16));
		}

		return strbuf.toString();
	}

	public void decrypt() throws Exception {

		// Instantiate the cipher
		Cipher cipher = Cipher.getInstance("AES");

		cipher.init(Cipher.DECRYPT_MODE, skeySpec);

		byte[] original = cipher.doFinal(encryptedPW);

		decryptedPW = new String(original);

	}

	@Override
	protected void onResume() {
		// if (sending) {
		super.onResume();
		mResumed = true;
		// Sticky notes received from Android
		// if
		// (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(getIntent().getAction())) {
		// NdefMessage[] messages = getNdefMessages(getIntent());
		// byte[] payload = messages[0].getRecords()[0].getPayload();
		// // setNoteBody(new String(payload));
		// setIntent(new Intent()); // Consume this intent.
		// }
		enableNdefExchangeMode();
		// }
	}

	@Override
	protected void onPause() {
		super.onPause();
		mResumed = false;
		mNfcAdapter.disableForegroundNdefPush(this);
	}

	@Override
	protected void onNewIntent(Intent intent) {
		// NDEF exchange mode
		if (!mWriteMode
				&& NfcAdapter.ACTION_NDEF_DISCOVERED.equals(intent.getAction())) {
			// NdefMessage[] msgs = getNdefMessages(intent);
			// promptForContent(msgs[0]);
		}

		// Tag writing mode
		if (mWriteMode
				&& NfcAdapter.ACTION_TAG_DISCOVERED.equals(intent.getAction())) {
			Tag detectedTag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
			writeTag(getNoteAsNdef(), detectedTag);
		}
	}

	private TextWatcher mTextWatcher = new TextWatcher() {

		public void onTextChanged(CharSequence arg0, int arg1, int arg2,
				int arg3) {

		}

		public void beforeTextChanged(CharSequence arg0, int arg1, int arg2,
				int arg3) {

		}

		public void afterTextChanged(Editable arg0) {
			if (mResumed) {
				mNfcAdapter.enableForegroundNdefPush(GetPW.this,
						getNoteAsNdef());
			}
		}
	};

	private View.OnClickListener mTagWriter = new View.OnClickListener() {

		public void onClick(View arg0) {

			// Write to a tag for as long as the dialog is shown.
			if (gotData) {
				disableNdefExchangeMode();
				enableTagWriteMode();

				// sending = true;

				new AlertDialog.Builder(GetPW.this)
						.setTitle("Touch tag to write")
						.setOnCancelListener(
								new DialogInterface.OnCancelListener() {

									public void onCancel(DialogInterface dialog) {
										disableTagWriteMode();
										enableNdefExchangeMode();
										// sending = false;
									}
								}).create().show();
			}
		}
	};

	private void promptForContent(final NdefMessage msg) { // READING MOOD
		new AlertDialog.Builder(this)
				.setTitle("Replace current content?")
				.setPositiveButton("Yes",
						new DialogInterface.OnClickListener() {
							public void onClick(DialogInterface arg0, int arg1) {
								String body = new String(msg.getRecords()[0]
										.getPayload());
								// setNoteBody(body);
							}
						})
				.setNegativeButton("No", new DialogInterface.OnClickListener() {
					public void onClick(DialogInterface arg0, int arg1) {

					}
				}).show();
	}

	// private void setNoteBody(String body) { //READING MOOD
	// Editable text = mNote;
	// text.clear();
	// text.append(body);
	// }

	private NdefMessage getNoteAsNdef() {
		// if (gotData) {
		oc = Db4oEmbedded.openFile(Db4oEmbedded.newConfiguration(),
				"/sdcard/MasterKeyDB");
		Data data = new Data(siteAppString, null, null, null);
		ObjectSet result = oc.queryByExample(data);
		listResult(result);
		oc.close();

		mNote = retrievedData.toString();

		byte[] textBytes = mNote.getBytes();

		NdefRecord textRecord = new NdefRecord(NdefRecord.TNF_MIME_MEDIA,
				"text/plain".getBytes(), new byte[] {}, textBytes);
		return new NdefMessage(new NdefRecord[] { textRecord });
		// }
		// return null;
	}

	NdefMessage[] getNdefMessages(Intent intent) {
		// Parse the intent
		NdefMessage[] msgs = null;
		String action = intent.getAction();
		if (NfcAdapter.ACTION_TAG_DISCOVERED.equals(action)
				|| NfcAdapter.ACTION_NDEF_DISCOVERED.equals(action)) {
			Parcelable[] rawMsgs = intent
					.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES);
			if (rawMsgs != null) {
				msgs = new NdefMessage[rawMsgs.length];
				for (int i = 0; i < rawMsgs.length; i++) {
					msgs[i] = (NdefMessage) rawMsgs[i];
				}
			} else {
				// Unknown tag type
				byte[] empty = new byte[] {};
				NdefRecord record = new NdefRecord(NdefRecord.TNF_UNKNOWN,
						empty, empty, empty);
				NdefMessage msg = new NdefMessage(new NdefRecord[] { record });
				msgs = new NdefMessage[] { msg };
			}
		} else {
			Log.d(TAG, "Unknown intent.");
			finish();
		}
		return msgs;
	}

	private void enableNdefExchangeMode() {
		mNfcAdapter.enableForegroundNdefPush(GetPW.this, getNoteAsNdef());
		mNfcAdapter.enableForegroundDispatch(GetPW.this, mNfcPendingIntent,
				mNdefExchangeFilters, null);
	}

	private void disableNdefExchangeMode() {
		mNfcAdapter.disableForegroundNdefPush(this);
		mNfcAdapter.disableForegroundDispatch(this);
	}

	private void enableTagWriteMode() {
		mWriteMode = true;
		IntentFilter tagDetected = new IntentFilter(
				NfcAdapter.ACTION_TAG_DISCOVERED);
		mWriteTagFilters = new IntentFilter[] { tagDetected };
		mNfcAdapter.enableForegroundDispatch(this, mNfcPendingIntent,
				mWriteTagFilters, null);
	}

	private void disableTagWriteMode() {
		mWriteMode = false;
		mNfcAdapter.disableForegroundDispatch(this);
	}

	boolean writeTag(NdefMessage message, Tag tag) {
		int size = message.toByteArray().length;

		try {
			Ndef ndef = Ndef.get(tag);
			if (ndef != null) {
				ndef.connect();

				if (!ndef.isWritable()) {
					toast("Tag is read-only.");
					return false;
				}
				if (ndef.getMaxSize() < size) {
					toast("Tag capacity is " + ndef.getMaxSize()
							+ " bytes, message is " + size + " bytes.");
					return false;
				}

				ndef.writeNdefMessage(message);
				toast("Wrote message to pre-formatted tag.");
				return true;
			} else {
				NdefFormatable format = NdefFormatable.get(tag);
				if (format != null) {
					try {
						format.connect();
						format.format(message);
						toast("Formatted tag and wrote message");
						return true;
					} catch (IOException e) {
						toast("Failed to format tag.");
						return false;
					}
				} else {
					toast("Tag doesn't support NDEF.");
					return false;
				}
			}
		} catch (Exception e) {
			toast("Failed to write tag");
		}

		return false;
	}

	private void toast(String text) {
		Toast.makeText(this, text, Toast.LENGTH_SHORT).show();
	}

}